package web

import (
	"commonUtils/utils"
	"sync"
	"time"
)

// WsConfig 连接配置
type WsConfig struct {
	Addr                 string
	WsURL                string
	HTTPSCertFile        string
	HTTPSKeyFile         string
	StaticURL            string
	StaticFolder         string
	ReadLimit            int64
	WriteBufferChanCount int
	SessionExpire        time.Duration

	// Conn 连接回调
	ProtoHandleFunc                func(*Conn, []byte) error
	DecompressFunc                 func([]byte) ([]byte, error)
	ErrorHandleFunc                func(*Conn, error)
	ConnectSuccessAfterSendMessage func(*Conn) []byte
	OnConnected                    func(*Conn)
	OnClose                        func(*Conn)
	WriteWait                      time.Duration
	PongWait                       time.Duration
	PingPeriod                     time.Duration

	// Server 回调
	OnCreateChannel    func(*Channel)
	OnChannelDeleted   func(*Channel)
	OnChannelNotExists func(string)

	// Channel 频道回调
	OnConnDisconnected      func(*Channel, *Conn)
	OnConnConnected         func(*Channel, *Conn)
	DeleteChannelWhenNoConn bool
}

// WsBuilder Builder
type WsBuilder struct {
	wsConfig *WsConfig
}

var muBuilder sync.Mutex
var builder *WsBuilder

// BuilderInstance init
func BuilderInstance() *WsBuilder {
	muBuilder.Lock()
	defer muBuilder.Unlock()
	if nil == builder {
		builder = &WsBuilder{&WsConfig{
			PingPeriod:              180 * time.Second,
			WriteWait:               30 * time.Second,
			ReadLimit:               10000000,
			WriteBufferChanCount:    100,
			SessionExpire:           2 * time.Hour,
			DeleteChannelWhenNoConn: true,
		}}
		builder.PongWait(builder.wsConfig.PingPeriod * 2)
	}
	return builder
}

func (b *WsBuilder) Addr(addr string) *WsBuilder {
	b.wsConfig.Addr = addr
	return b
}

func (b *WsBuilder) HTTPSCertFile(path string) *WsBuilder {
	if utils.IsFile(path) {
		b.wsConfig.HTTPSCertFile = path
	} else {
		utils.Warning("HTTPSCertFile path %s is not exists", path)
	}
	return b
}

func (b *WsBuilder) HTTPSKeyFile(path string) *WsBuilder {
	if utils.IsFile(path) {
		b.wsConfig.HTTPSKeyFile = path
	} else {
		utils.Warning("HTTPSKeyFile path %s is not exists", path)
	}
	return b
}

func (b *WsBuilder) WsURL(wsUrl string) *WsBuilder {
	b.wsConfig.WsURL = wsUrl
	return b
}

func (b *WsBuilder) StaticURL(staticURL string) *WsBuilder {
	b.wsConfig.StaticURL = staticURL
	return b
}

func (b *WsBuilder) StaticFolder(staticFolder string) *WsBuilder {
	if utils.IsDir(staticFolder) {
		b.wsConfig.StaticFolder = staticFolder
	} else {
		utils.Warning("StaticFolder path %s is not exists", staticFolder)
	}
	return b
}

func (b *WsBuilder) ProtoHandleFunc(f func(*Conn, []byte) error) *WsBuilder {
	b.wsConfig.ProtoHandleFunc = f
	return b
}

func (b *WsBuilder) DecompressFunc(f func([]byte) ([]byte, error)) *WsBuilder {
	b.wsConfig.DecompressFunc = f
	return b
}

func (b *WsBuilder) ErrorHandleFunc(f func(conn *Conn, err error)) *WsBuilder {
	b.wsConfig.ErrorHandleFunc = f
	return b
}
func (b *WsBuilder) ConnectSuccessAfterSendMessage(msg func(conn *Conn) []byte) *WsBuilder {
	b.wsConfig.ConnectSuccessAfterSendMessage = msg
	return b
}
func (b *WsBuilder) OnConnected(f func(*Conn)) *WsBuilder {
	b.wsConfig.OnConnected = f
	return b
}

func (b *WsBuilder) OnClose(f func(*Conn)) *WsBuilder {
	b.wsConfig.OnClose = f
	return b
}

func (b *WsBuilder) WriteWait(t time.Duration) *WsBuilder {
	b.wsConfig.WriteWait = t
	return b
}

func (b *WsBuilder) PongWait(t time.Duration) *WsBuilder {
	b.wsConfig.PongWait = t
	return b
}

func (b *WsBuilder) PingPeriod(t time.Duration) *WsBuilder {
	b.wsConfig.PingPeriod = t
	return b
}

func (b *WsBuilder) OnConnDisconnected(f func(*Channel, *Conn)) *WsBuilder {
	b.wsConfig.OnConnDisconnected = f
	return b
}

func (b *WsBuilder) OnConnConnected(f func(*Channel, *Conn)) *WsBuilder {
	b.wsConfig.OnConnConnected = f
	return b
}

func (b *WsBuilder) OnCreateChannel(f func(*Channel)) *WsBuilder {
	b.wsConfig.OnCreateChannel = f
	return b
}

func (b *WsBuilder) OnChannelDeleted(f func(*Channel)) *WsBuilder {
	b.wsConfig.OnChannelDeleted = f
	return b
}

func (b *WsBuilder) OnChannelNotExists(f func(string)) *WsBuilder {
	b.wsConfig.OnChannelNotExists = f
	return b
}

func (b *WsBuilder) DeleteChannelWhenNoConn(bb bool) *WsBuilder {
	b.wsConfig.DeleteChannelWhenNoConn = bb
	return b
}

func (b *WsBuilder) ReadLimit(limit int64) *WsBuilder {
	b.wsConfig.ReadLimit = limit
	return b
}

func (b *WsBuilder) WriteBufferChanCount(count int) *WsBuilder {
	b.wsConfig.WriteBufferChanCount = count
	return b
}

func (b *WsBuilder) SessionExpire(t time.Duration) *WsBuilder {
	b.wsConfig.SessionExpire = t
	return b
}
